home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-12-14 | 46.5 KB | 2,004 lines |
- Newsgroups: comp.sources.misc
- From: byron@archone.tamu.edu (Byron Rakitzis)
- Subject: v26i111: pico - A picture editor for SGI, Sun, Part01/01
- Message-ID: <1991Dec15.021403.21349@sparky.imd.sterling.com>
- X-Md4-Signature: 9a12d1665543613b332f8c20c2b7cc6b
- Date: Sun, 15 Dec 1991 02:14:03 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: byron@archone.tamu.edu (Byron Rakitzis)
- Posting-number: Volume 26, Issue 111
- Archive-name: pico/part01
- Environment: SGI, Sun4, ANSI-C
-
- I've spent some time working on a picture editor described in Gerard
- Holzman's book "The Digital Darkroom". I don't really have the time to
- take this program all the way, so I thought I'd offer to the net what
- results I have so far. This program is *not* a full-blown implementation
- of pico. However, I think the code is interesting enough that someone
- might be able to do something quite useful with it without too much effort.
-
- I have a version of pico which compiles MIPS and SPARC code on the fly,
- and which can deal with simple C expressions which refer to bitmaps in
- terms of cartesian coordinates (x,y). It supports 512x512 8-bit
- greyscale image files (in pgm format).
-
- Despite its limitations, it is a fun toy to play with. Compared to
- "popi", a pico interpreter posted to the net a few months back, this
- program has far fewer features, but also runs one or two orders of
- magnitude faster (I am not making this up).
-
- Byron.
- ---------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: README Makefile alloc.c dpy.c expr.y file.c gen.c main.c
- # mipsgen.c mk.c nodpy.c patchlevel.h pico.h sparcgen.c
- # Wrapped by kent@sparky on Sat Dec 14 20:00:03 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 1)."'
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(5093 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- Xpico -- 1st approximation, Byron Rakitzis, 12/10/91.
- X
- XThis is a first stab at an implementation of pico, the picture editor
- Xfrom Bell Labs described in Gerard Holzman's book "The Digital
- XDarkroom".
- X
- XThis program is *not* a full-blown implementation of pico. However, I
- Xthink the code is interesting enough that someone might be able to do
- Xsomething quite useful with it without too much effort.
- X
- XHOW TO BUILD PICO:
- X
- XPico runs on SGI's and Sun-4's. Edit the Makefile to get the right
- Xcompiler and LDFLAGS. On a Sun4, you will need gcc or Sun's ansi
- Xcc, since pico is written with prototypes and new-style definitions.
- X
- XHOW TO USE IT:
- X
- XThere are two options to pico, "-n" and "-d". "-n" suppresses the
- Xdisplay output, and "-d" provides an assembly dump of the generated
- Xcode after each expression is typed (using "dis" on the SGI and "adb"
- Xon the Sun).
- X
- XIf you type "pico" you are prompted with a ">". You can now try typing
- Xin a C expression involving x and y. The greyscale value of the point
- X[x,y] is determined by the value of the expression you type. e.g.,
- X
- X > x+y
- X
- Xcreates a series of diagonal bands, since at x+y == 256 the grey
- Xvalue wraps from white to black. x*y is striking, as is x^y, x*x+y*y
- Xand many others.
- X
- XYou can refer to the current image as old[x,y], e.g.,
- X
- X > old[y,x]
- X
- Xrotates the current image 90 degrees. The "u" command performs one
- Xlevel of undo, alternating between the current and previous images.
- X
- XIf you create a file that you like, you can write it out (in pgm
- Xformat) with the "w" command. Use double quotes to quote any special
- Xcharacters in the filename. i.e.,
- X
- X > w foo
- Xbut
- X > w "/tmp/foo"
- X
- XSimilarly, "r" can be used to read pgm files (which for now must be
- X512x512, 8-bit greyscale images).
- X
- XOnce you have a file, you can always refer to it by the shorthand "$n"
- Xwhere n is the number of the file in the order it was read/written.
- XType "f" to see what files you have in memory.
- X
- XFor example, to combine chris and dmr (the two sample bitmaps in the
- Xftp directory) so that chris fades into dmr from left to right, you can
- Xtry:
- X
- X > r dmr
- X > r chris
- X > (x*dmr + (X-x)*chris) / (2*X)
- X [this can also be entered as]
- X > (x*$1 + (X-x)*$2) / (2*X)
- X
- Xto reflect dmr's face along the line y=256, do:
- X
- X y < Y/2 ? dmr[x,Y-y] : dmr
- X
- X(X refers to the constant 512, the maximum x coordinate. The other
- Xbuilt in constants are Y (obvious) and Z, the maximum brightness level,
- X255.)
- X
- XFinally, to quit type "q" or control-D.
- X
- XHOW IT WORKS:
- X
- XThe program is made up of a parser of C expressions, a simple rd code
- Xgenerator for the MIPS and SPARC architectures, minimal display support
- Xfor the GL (Silicon Graphics) library, and file I/O in pgm format. The
- Ximage format is hardcoded at 512*512, 8-bit greyscale. An expression is
- Xcompiled straight into an array and then gets called by pico in order
- Xto perform the operations on the image as fast as possible. This pico
- Xis at least an order of magnitude faster (if not more) than the popi
- Xposted to the net a few months back.
- X
- XTo use this program you must be on an SGI or a Sun. The Sun version
- Xcurrently has no visual support, so you must explicitly write out pgm
- Xfiles and use "xloadimage" or some similar program to view the pico
- Xoutput.
- X
- XTHINGS TO DO:
- X
- XI would consider extending the program in the following ways, though I
- Xdon't have the time for it right now:
- X
- X1) Support different displays. Since the format of pico images is so
- Xsimple, 8-bit greyscale, it should be easy to pop up images on just
- Xabout any kind of computer with a color display. I have used pico
- Xcrudely under X-windows by writing a pgm file out to /tmp and then
- Xrunning "xloadimage /tmp/pico" in order to view the file.
- X
- X2) Extend the pico language. Right now only C expressions are
- Xsupported. The only two variables recognized are x and y. This is a
- Xdrawback, but as I mentioned, this isn't a full-blown pico. The command
- Xset is limited to r, w, f, u, q. (read, write, showfiles, undo, quit)
- X
- X3) Add support for polar coordinates, transcendental functions, and so
- Xon. The current implementation works only with the MIPS integer unit,
- Xi.e., add, subtract, multiply, divide and the bit operations. The SPARC
- Xport is even cruder; a function call is made for every multiply, divide
- Xand mod operation, since there is no hardware multiply etc. A future
- Xversion may address this problem by performing strength reduction on
- Xloops, but this is really beyond the scope of the project I started.
- X(However, I do perform strength reduction on power of 2 multiplies
- Xand divides by substituting a shift.)
- X
- X4) Support color images. A very interesting project would be to support
- Xarbitrary 32-bit color images, i.e., with alpha channel. This might
- Xactually be of use to people who need to, say, boost the alpha channel
- Xof a particular image file. This also entails supporting "real" image
- Xfile formats like rla.
- X
- X4) Support new architectures. I wrote pico on the MIPS, and spent about
- X2 afternoons porting it to the SPARC. Consequently, the quality of the
- XSPARC port is probably quite mediocre. Porting to other RISC machines,
- Xhowever should be equally straightforward.
- END_OF_FILE
- if test 5093 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(216 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X# For sgi
- XCC=cc -prototypes -O -g
- XLDFLAGS = -lgl
- X
- X# For sun4
- X#CC=gcc -Wall -O -g
- X
- Xobjs = y.tab.o main.o mk.o gen.o dpy.o file.o alloc.o
- X
- Xpico: $(objs)
- X $(CC) -o pico $(objs) $(LDFLAGS)
- X
- Xy.tab.c: expr.y
- X yacc expr.y
- END_OF_FILE
- if test 216 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'alloc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'alloc.c'\"
- else
- echo shar: Extracting \"'alloc.c'\" \(2113 characters\)
- sed "s/^X//" >'alloc.c' <<'END_OF_FILE'
- X/* alloc.c: a simple single-arena allocator for command-line-lifetime allocation */
- X
- X#include "pico.h"
- X
- Xtypedef struct Block Block;
- X
- Xstatic struct Block {
- X size_t used, size;
- X char *mem;
- X Block *n;
- X} *fl, *ul;
- X
- X/* alignto() works only with power of 2 blocks and assumes 2's complement arithmetic */
- X#define alignto(m, n) ((m + n - 1) & ~(n - 1))
- X#define BLOCKSIZE ((size_t) 4096)
- X
- Xextern void *ealloc(size_t n) {
- X extern void *malloc(size_t);
- X void *p = malloc(n);
- X if (p == NULL) {
- X perror("malloc");
- X exit(1);
- X }
- X return p;
- X}
- X
- X/* gets a block from malloc space and places it at the head of the used-list */
- X
- Xstatic void getblock(size_t n) {
- X Block *r, *p;
- X
- X for (r = fl, p = NULL; r != NULL; p = r, r = r->n)
- X if (n <= r->size)
- X break;
- X
- X if (r != NULL) {
- X if (p != NULL)
- X p->n = r->n;
- X else
- X fl = r->n;
- X } else {
- X r = ealloc(sizeof *r);
- X r->mem = ealloc(alignto(n, BLOCKSIZE));
- X r->size = alignto(n, BLOCKSIZE);
- X }
- X
- X r->used = 0;
- X r->n = ul;
- X ul = r;
- X}
- X
- X/*
- X A fast single-arena allocator. Looks at the current block, and if there is not enough room,
- X it goes to getblock() for more. "ul" stands for "used list", and the head of the list is the
- X current block.
- X*/
- X
- Xextern void *alloc(size_t n) {
- X char *ret;
- X n = alignto(n, sizeof (size_t)); /* a good guess about how to align data? */
- X if (ul == NULL || n + ul->used >= ul->size)
- X getblock(n);
- X ret = ul->mem + ul->used;
- X ul->used += n;
- X return ret;
- X}
- X
- X/*
- X Frees memory from nalloc space by putting it on the freelist. Returns free blocks to the
- X system, retaining at least MAXMEM bytes worth of blocks for nalloc.
- X*/
- X
- X#define MAXMEM 500000
- X
- Xextern void afree() {
- X Block *r;
- X size_t count;
- X if (ul == NULL)
- X return;
- X for (r = ul; r->n != NULL; r = r->n)
- X ;
- X r->n = fl;
- X fl = ul;
- X ul = NULL;
- X for (r = fl, count = r->size; r->n != NULL; r = r->n, count += r->size) {
- X if (count >= MAXMEM) {
- X Block *tmp = r;
- X r = r->n;
- X tmp->n = NULL; /* terminate the freelist */
- X while (r != NULL) { /* free memory off the tail of the freelist */
- X tmp = r->n;
- X free(r->mem);
- X free(r);
- X r = tmp;
- X }
- X return;
- X }
- X }
- X}
- END_OF_FILE
- if test 2113 -ne `wc -c <'alloc.c'`; then
- echo shar: \"'alloc.c'\" unpacked with wrong size!
- fi
- # end of 'alloc.c'
- fi
- if test -f 'dpy.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dpy.c'\"
- else
- echo shar: Extracting \"'dpy.c'\" \(680 characters\)
- sed "s/^X//" >'dpy.c' <<'END_OF_FILE'
- X#include "pico.h"
- X
- X#ifdef sgi
- X#include <gl/gl.h>
- Xstatic void initdisplay() {
- X static init;
- X if (!init) {
- X init = 1;
- X prefposition(200, 199 + DEF_X, 200, 199 + DEF_Y);
- X foreground();
- X winopen("pico");
- X RGBmode();
- X gconfig();
- X }
- X}
- X
- X/*
- X pico works with [0,0] in the top left, but sgi windows put it in
- X the bottom left
- X*/
- X
- Xextern void display(unsigned char *data) {
- X unsigned long scr[DEF_X * DEF_Y];
- X int i,j;
- X initdisplay();
- X for (i = 0, j = DEF_X*(DEF_Y-1); i < DEF_Y*DEF_X; i++, (++j&(DEF_X-1)) || j -= 2*DEF_X)
- X scr[j] = data[i] | (data[i]<<8) | (data[i]<<16);
- X lrectwrite(0, 0, DEF_X - 1, DEF_Y - 1, scr);
- X}
- X#else
- Xextern void display(unsigned char *data) {
- X}
- X#endif
- END_OF_FILE
- if test 680 -ne `wc -c <'dpy.c'`; then
- echo shar: \"'dpy.c'\" unpacked with wrong size!
- fi
- # end of 'dpy.c'
- fi
- if test -f 'expr.y' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'expr.y'\"
- else
- echo shar: Extracting \"'expr.y'\" \(4275 characters\)
- sed "s/^X//" >'expr.y' <<'END_OF_FILE'
- X%{
- X#include <stdlib.h>
- X#include <ctype.h>
- X#include <stdio.h>
- X#include "pico.h"
- X
- Xstatic int yylex(void);
- Xstatic void yyerror(char *);
- X
- Xstatic lastnum;
- Xstatic char lastname[1024];
- X%}
- X
- X%union {
- X Tree *node;
- X int num;
- X}
- X
- X%term ANDAND OROR EQ NE LE GE LL RR ICON NAME
- X%type <node> cmd expr ss or xor and eq rel shift
- X%type <node> plus times factor coord
- X%type <num> file
- X
- X%%
- X
- Xpico : /* empty */ { tree = NULL; YYACCEPT; }
- X | '\n' { tree = NULL; YYACCEPT; }
- X | error '\n' { tree = NULL; YYABORT; }
- X | cmd '\n' { tree = $1; YYACCEPT; }
- X
- Xcmd : expr
- X | 'w' NAME { $$ = mkun(Write,lastname); }
- X | 'r' NAME { $$ = mkun(Read,lastname); }
- X | 'f' { $$ = mkempty(Files); }
- X | 'u' { $$ = mkempty(Undo); }
- X | 'q' { $$ = mkempty(Quit); }
- X
- Xexpr : ss
- X | ss '?' expr ':' expr { $$ = mkCond($1,$3,$5); }
- X
- Xss : or
- X | ss ANDAND or { $$ = mk(Andalso,$1,$3); }
- X | ss OROR or { $$ = mk(Orelse,$1,$3); }
- X
- Xor : xor
- X | or '|' xor { $$ = mk(Or,$1,$3); }
- X
- Xxor : and
- X | xor '^' and { $$ = mk(Xor,$1,$3); }
- X
- Xand : eq
- X | and '&' eq { $$ = mk(And,$1,$3); }
- X
- Xeq : rel
- X | eq EQ rel { $$ = mk(Eq,$1,$3); }
- X | eq NE rel { $$ = mk(Ne,$1,$3); }
- X
- Xrel : shift
- X | rel '<' shift { $$ = mk(Lt,$1,$3); }
- X | rel '>' shift { $$ = mk(Gt,$1,$3); }
- X | rel LE shift { $$ = mk(Ge,$1,$3); }
- X | rel GE shift { $$ = mk(Le,$1,$3); }
- X
- Xshift : plus
- X | shift LL plus { $$ = mk(Ll,$1,$3); }
- X | shift RR plus { $$ = mk(Rr,$1,$3); }
- X
- X
- Xplus : times
- X | plus '+' times { $$ = mk(Add,$1,$3); }
- X | plus '-' times { $$ = mk(Sub,$1,$3); }
- X
- Xtimes : factor
- X | times '*' factor { $$ = mk(Mult,$1,$3); }
- X | times '/' factor { $$ = mk(Div,$1,$3); }
- X | times '%' factor { $$ = mk(Mod,$1,$3); }
- X
- Xfactor : 'x' { $$ = mkempty(Xcoord); }
- X | 'y' { $$ = mkempty(Ycoord); }
- X | ICON { $$ = mkNum(lastnum); }
- X | '+' factor { $$ = $2; }
- X | '-' factor { $$ = mkun(Neg,$2); }
- X | '!' factor { $$ = mkun(Bang,$2); }
- X | '~' factor { $$ = mkun(Not,$2); }
- X | file coord { $$ = mkCoord($1,$2); }
- X | '(' expr ')' { $$ = $2; }
- X
- Xfile : NAME { $$ = findfile(lastname); }
- X | '$' ICON { $$ = lastnum + 1; }
- X
- Xcoord : /* nada */ { $$ = NULL; }
- X | '[' expr ',' expr ']' { $$ = mk(Add,$2,mk(Mult,$4,mkNum(DEF_Y))); }
- X%%
- X
- Xstatic int yylex() {
- X char *l;
- X int c;
- X while ((c = getchar()) == ' ' || c == '\t')
- X ;
- X switch (c) {
- X case EOF:
- X saw_eof = 1;
- X return 0;
- X case '\n':
- X case '?': case ':':
- X case '-': case '+':
- X case '*': case '/': case '%':
- X case '~': case '^':
- X case '(': case ')':
- X case '[': case ']':
- X case ',': case '$':
- X return c;
- X case '&':
- X if ((c = getchar()) == '&')
- X return ANDAND;
- X ungetc(c,stdin);
- X return '&';
- X case '|':
- X if ((c = getchar()) == '|')
- X return OROR;
- X ungetc(c,stdin);
- X return '|';
- X case '>':
- X if ((c = getchar()) == '>')
- X return RR;
- X else if (c == '=')
- X return GE;
- X ungetc(c,stdin);
- X return '>';
- X case '<':
- X if ((c = getchar()) == '<')
- X return LL;
- X else if (c == '=')
- X return LE;
- X ungetc(c,stdin);
- X return '<';
- X case '=':
- X if ((c = getchar()) == '=')
- X return EQ;
- X ungetc(c,stdin);
- X return '=';
- X case '!':
- X if ((c = getchar()) == '=')
- X return NE;
- X ungetc(c,stdin);
- X return '!';
- X case '\"':
- X l = lastname;
- X while ((c = getchar()) != '\"' && c != '\n' && c != EOF)
- X *l++ = c;
- X if (c != '\"')
- X ungetc(c,stdin);
- X *l = '\0';
- X return NAME;
- X default:
- X if (isdigit(c)) {
- X lastnum = c - '0';
- X while (isdigit(c = getchar()))
- X lastnum = (lastnum * 10) + (c - '0');
- X ungetc(c,stdin);
- X return ICON;
- X } else {
- X l = lastname;
- X while (1) {
- X *l++ = c;
- X switch (c = getchar()) {
- X case EOF: case ' ': case '\t': case '\n':
- X case '?': case ':': case '-': case '+':
- X case '*': case '/': case '%':
- X case '~': case '^': case '(': case ')':
- X case '<': case '>': case '[': case ']':
- X case '&': case '|': case '=': case '!':
- X case '\"': case ',':
- X ungetc(c,stdin);
- X if (l == lastname + 1)
- X switch (*lastname) {
- X case 'x': case 'y': case 'u':
- X case 'f': case 'q': case 'w':
- X case 'r':
- X return *lastname;
- X case 'X':
- X lastnum = DEF_X;
- X return ICON;
- X case 'Y':
- X lastnum = DEF_Y;
- X return ICON;
- X case 'Z':
- X lastnum = 255;
- X return ICON;
- X }
- X *l = '\0';
- X return NAME;
- X }
- X }
- X }
- X }
- X}
- X
- Xstatic void yyerror(char *err) {
- X fprintf(stderr, "%s\n", err);
- X}
- END_OF_FILE
- if test 4275 -ne `wc -c <'expr.y'`; then
- echo shar: \"'expr.y'\" unpacked with wrong size!
- fi
- # end of 'expr.y'
- fi
- if test -f 'file.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'file.c'\"
- else
- echo shar: Extracting \"'file.c'\" \(2097 characters\)
- sed "s/^X//" >'file.c' <<'END_OF_FILE'
- X#include <string.h>
- X#include <ctype.h>
- X#include "pico.h"
- X
- Xint nfiles = 2;
- X
- XBuf buf[NFILES];
- X
- Xextern int findfile(char *name) {
- X int i;
- X if (strcmp(name, "old") == 0)
- X return 1;
- X for (i = 2; i < nfiles; i++)
- X if (strcmp(buf[i].name, name) == 0)
- X return i;
- X return -1;
- X}
- X
- Xextern void showfiles() {
- X int i;
- X if (nfiles == 2) {
- X fprintf(stderr, "no files open\n");
- X } else {
- X for (i = 2; i < nfiles; i++)
- X printf("$%d = %s\n", i - 1, buf[i].name);
- X }
- X}
- X
- Xextern void writefile(char *name) {
- X int f = findfile(name);
- X FILE *fp = fopen(name, "w");
- X if (fp == NULL) {
- X perror(name);
- X return;
- X }
- X fprintf(fp, "P5 %d %d 255\n", DEF_X, DEF_Y);
- X fwrite(buf[0].data, 1, DEF_X * DEF_Y, fp);
- X fclose(fp);
- X if (f < 0) {
- X if (nfiles >= NFILES)
- X return;
- X f = nfiles++;
- X buf[f].name = strdup(name);
- X buf[f].data = ealloc(DEF_X * DEF_Y);
- X }
- X memcpy(buf[f].data, buf[0].data, DEF_X * DEF_Y);
- X}
- X
- X#define failif(x,y) if (x) {y; f = -1; goto fail;}
- X#define next fgetc(fp)
- X
- Xextern int readfile(char *name) {
- X FILE *fp = fopen(name, "r");
- X int c,i,f = findfile(name);
- X failif(f > 0 && nfiles >= NFILES, fprintf(stderr, "too many open files\n"))
- X failif(fp == NULL, perror(name))
- X failif(next != 'P' || next != '5', fprintf(stderr, "%s: bad magic number\n", name))
- X while (isspace(c = next))
- X ;
- X failif(!isdigit(c), fprintf(stderr, "%s: expected a decimal number, saw: %c\n", name, c))
- X for (i = c - '0'; isdigit(c = next); i = i*10 + c-'0')
- X ;
- X failif(i != DEF_X, fprintf(stderr, "%s: expected an x-coordinate of %d\n", name, DEF_X))
- X while (isspace(c))
- X c = next;
- X for (i = c - '0'; isdigit(c = next); i = i*10 + c-'0')
- X ;
- X failif(i != DEF_Y, fprintf(stderr, "%s: expected a y-coordinate of %d\n", name, DEF_Y))
- X while (isspace(c))
- X c = next;
- X for (i = c - '0'; isdigit(c = next); i = i*10 + c-'0')
- X ;
- X failif(i != 255, fprintf(stderr, "%s: expected a grey scale of 255, saw\n", name, i))
- X if (!isspace(c))
- X ungetc(c,fp);
- X if (f < 0) {
- X f = nfiles++;
- X buf[f].name = strdup(name);
- X buf[f].data = ealloc(DEF_X * DEF_Y);
- X }
- X fread(buf[f].data, 1, DEF_X * DEF_Y, fp);
- Xfail:
- X fclose(fp);
- X return f;
- X}
- END_OF_FILE
- if test 2097 -ne `wc -c <'file.c'`; then
- echo shar: \"'file.c'\" unpacked with wrong size!
- fi
- # end of 'file.c'
- fi
- if test -f 'gen.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'gen.c'\"
- else
- echo shar: Extracting \"'gen.c'\" \(67 characters\)
- sed "s/^X//" >'gen.c' <<'END_OF_FILE'
- X#ifdef sgi
- X#include "mipsgen.c"
- X#else
- X#include "sparcgen.c"
- X#endif
- END_OF_FILE
- if test 67 -ne `wc -c <'gen.c'`; then
- echo shar: \"'gen.c'\" unpacked with wrong size!
- fi
- # end of 'gen.c'
- fi
- if test -f 'main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'main.c'\"
- else
- echo shar: Extracting \"'main.c'\" \(1507 characters\)
- sed "s/^X//" >'main.c' <<'END_OF_FILE'
- X#include <setjmp.h>
- X#include <string.h>
- X#include "pico.h"
- X
- Xint debug, saw_eof;
- XTree *tree;
- X
- Xstatic void run(Tree *t);
- X
- Xstatic disp = 1;
- Xstatic jmp_buf jb;
- X
- Xextern int main(int argc, char *argv[]) {
- X extern int optind;
- X int c, err = 0;
- X
- X while ((c = getopt(argc, argv, "dn")) != -1)
- X if (c == 'd')
- X debug = 1;
- X else if (c == 'n')
- X disp = 0;
- X else
- X err = 1;
- X if (err || argc - optind != 0) {
- X fprintf(stderr, "usage: pico [-nd]");
- X exit(1);
- X }
- X buf[0].data = ealloc(DEF_X * DEF_Y);
- X buf[1].data = ealloc(DEF_X * DEF_Y);
- X setjmp(jb);
- X while (1) {
- X fprintf(stderr, "> ");
- X fflush(stderr);
- X yyparse();
- X if (saw_eof)
- X return 0;
- X if (tree != NULL)
- X run(tree);
- X afree();
- X }
- X}
- X
- X#define swap(x,y) {\
- X unsigned char *tmp = x;\
- X x = y;\
- X y = tmp;\
- X}
- X
- Xstatic void run(Tree *t) {
- X int f;
- X switch (t->t) {
- X case Quit:
- X exit(0);
- X case Undo:
- X swap(buf[0].data, buf[1].data);
- X if (disp)
- X display(buf[0].data);
- X break;
- X case Read:
- X if ((f = readfile(t->kids[0])) > 0) {
- X swap(buf[0].data, buf[1].data);
- X memcpy(buf[0].data, buf[f].data, DEF_X * DEF_Y);
- X if (disp)
- X display(buf[0].data);
- X }
- X break;
- X case Write:
- X writefile(t->kids[0]);
- X break;
- X case Files:
- X showfiles();
- X break;
- X default:
- X swap(buf[0].data, buf[1].data);
- X compile(t);
- X#ifdef sgi
- X if (debug)
- X system("dis pico.out");
- X#else
- X if (debug)
- X system("echo ',-1?' | adb " DUMPFILE);
- X#endif
- X if (disp)
- X display(buf[0].data);
- X break;
- X }
- X}
- X
- Xextern void error(char *s) {
- X fprintf(stderr, "%s\n", s);
- X longjmp(jb,1);
- X}
- END_OF_FILE
- if test 1507 -ne `wc -c <'main.c'`; then
- echo shar: \"'main.c'\" unpacked with wrong size!
- fi
- # end of 'main.c'
- fi
- if test -f 'mipsgen.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mipsgen.c'\"
- else
- echo shar: Extracting \"'mipsgen.c'\" \(9124 characters\)
- sed "s/^X//" >'mipsgen.c' <<'END_OF_FILE'
- X#include <sys/cachectl.h>
- X#include <a.out.h>
- X#include <unistd.h>
- X#include <string.h>
- X#include "pico.h"
- X
- Xtypedef unsigned long Inst;
- X
- Xstatic void gen(Tree *t);
- Xstatic void binop(Tree *t, int s1, int s2, int d);
- Xstatic void binconst(Tree *t, int s1, int s2, int d);
- Xstatic void dodump(Inst *, int);
- Xstatic void clearregs(void);
- Xstatic void freereg(int);
- Xstatic int findreg(void);
- X
- Xstatic Inst *code;
- Xstatic boolean, last = 8, regs[8], spp, sppmax, result;
- X
- X#define zero 0
- X#define tmp 1
- X#define base 4 /* first arg */
- X#define offset 5 /* second arg */
- X#define rx 16 /* first saved reg */
- X#define ry 17
- X#define sp 29
- X#define ra 31
- X
- X#define RTYPE(a,b,c,d) (d|(c<<11)|(b<<16)|(a<<21))
- X#define STYPE(a,b,c,d) (d|(c<<11)|(b<<6)|(a<<16))
- X#define ITYPE(a,b,c,d) ((d<<26)|(a<<21)|(b&0xffff)|(c<<16))
- X
- X#define _ADDU(a,b,c) *code++ = RTYPE(a,b,c,041)
- X#define _SUBU(a,b,c) *code++ = RTYPE(a,b,c,043)
- X#define _MULTU(a,b) *code++ = RTYPE(a,b,0,031)
- X#define _DIVU(a,b) *code++ = RTYPE(a,b,0,033)
- X#define _MFLO(a) *code++ = RTYPE(0,0,a,022)
- X#define _MFHI(a) *code++ = RTYPE(0,0,a,020)
- X#define _SLTU(a,b,c) *code++ = RTYPE(a,b,c,053)
- X#define _XOR(a,b,c) *code++ = RTYPE(a,b,c,046)
- X#define _OR(a,b,c) *code++ = RTYPE(a,b,c,045)
- X#define _NOR(a,b,c) *code++ = RTYPE(a,b,c,047)
- X#define _AND(a,b,c) *code++ = RTYPE(a,b,c,044)
- X#define _ANDI(a,b,c) *code++ = ITYPE(a,b,c,014)
- X#define _XORI(a,b,c) *code++ = ITYPE(a,b,c,016)
- X#define _ORI(a,b,c) *code++ = ITYPE(a,b,c,015)
- X#define _ADDIU(a,b,c) *code++ = ITYPE(a,b,c,011)
- X#define _SLTIU(a,b,c) *code++ = ITYPE(a,b,c,013)
- X#define _LBU(a,b,c) *code++ = ITYPE(b,c,a,044)
- X#define _SB(a,b,c) *code++ = ITYPE(b,c,a,050)
- X#define _LW(a,b,c) *code++ = ITYPE(b,c,a,043)
- X#define _SW(a,b,c) *code++ = ITYPE(b,c,a,053)
- X#define _LUI(a,b) *code++ = ITYPE(0,b,a,017)
- X#define _BNE(a,b,c) ITYPE(b,c,a,005)
- X#define _BEQ(a,b,c) ITYPE(b,c,a,004)
- X#define _JR(a) *code++ = RTYPE(a,0,0,010)
- X#define _SLL(a,b,c) *code++ = STYPE(a,b,c,000)
- X#define _SRL(a,b,c) *code++ = STYPE(a,b,c,002)
- X#define _SRLV(a,b,c) *code++ = RTYPE(a,b,c,006)
- X#define _SLLV(a,b,c) *code++ = RTYPE(b,a,c,004)
- X#define _SRLV(a,b,c) *code++ = RTYPE(a,b,c,006)
- X#define _NOP *code++ = 0x0
- X
- X#define _PUSH(a) {\
- X _SW(a,sp,spp);\
- X spp += 4;\
- X if (spp > sppmax)\
- X sppmax = spp;\
- X}
- X
- X#define _POP(a) {\
- X spp -= 4;\
- X _LW(a,sp,spp);\
- X}
- X
- Xstatic void loadimm(int i, int j) {
- X if (j < 0 && j >= -32768) {
- X _ADDIU(zero,j,i);
- X } else if ((Inst) j > 65535) {
- X Inst k = (Inst) j >> 16;
- X Inst l = (Inst) j & 65535;
- X _LUI(i,k);
- X if (l != 0)
- X _ORI(i,l,i);
- X } else {
- X _ORI(zero,((Inst)j),i);
- X }
- X}
- X
- Xextern void compile(Tree *t) {
- X Inst prog[1024], *remem1, *remem2;
- X void (*progp)() = (void (*)()) prog;
- X code = prog;
- X clearregs();
- X last = findreg();
- X code = prog;
- X _ADDIU(sp,0,sp); /* value is or'ed in later */
- X _PUSH(rx);
- X _PUSH(ry);
- X loadimm(ry,DEF_Y-1);
- X remem1 = code;
- X loadimm(rx,DEF_X-1);
- X remem2 = code;
- X gen(t);
- X _ADDU(base,offset,tmp);
- X _SB(result,tmp,0);
- X _ADDIU(offset,-1,offset);
- X *code = _BNE(zero,rx,remem2-code-1); code++;
- X _ADDIU(rx,-1,rx);
- X *code = _BNE(zero,ry,remem1-code-1); code++;
- X _ADDIU(ry,-1,ry);
- X _POP(ry);
- X _POP(rx);
- X _JR(ra);
- X _ADDIU(sp,sppmax,sp);
- X *prog |= (-sppmax)&0xffff;
- X dodump(prog, (code - prog) * sizeof (Inst));
- X cacheflush(prog, sizeof prog, ICACHE);
- X progp(buf[0].data, (DEF_X*DEF_Y) - 1);
- X}
- X
- Xstatic void gen(Tree *t) {
- X Inst *remem;
- X int i, saved, b1, b2;
- X switch (t->t) {
- X case Num:
- X if (t->i == 0) {
- X result = zero;
- X boolean = 1;
- X } else {
- X loadimm(result = last, t->i);
- X boolean = !(t->i & ~1);
- X }
- X break;
- X case Xcoord:
- X result = rx;
- X boolean = 0;
- X break;
- X case Ycoord:
- X result = ry;
- X boolean = 0;
- X break;
- X case Bang:
- X gen(t->kids[0]);
- X _SLTIU(result,1,last);
- X result = last;
- X boolean = 1;
- X break;
- X case Not:
- X gen(t->kids[0]);
- X _NOR(result,0,last);
- X result = last;
- X boolean = 0;
- X break;
- X case Neg:
- X gen(t->kids[0]);
- X _SUBU(zero,result,last);
- X result = last;
- X boolean = 0;
- X break;
- X case Cond:
- X gen(t->kids[0]); /* test */
- X remem = code;
- X *code++ = _BEQ(zero,result,0);
- X _NOP;
- X gen(t->kids[1]); /* iftrue */
- X b1 = boolean;
- X if (result != last)
- X _ADDU(result,zero,last);
- X *remem |= code - remem;
- X remem = code - 1;
- X *code = code[-1];
- X code[-1] = _BEQ(zero,zero,0); /* fill delay slot */
- X code++;
- X gen(t->kids[2]); /* iffalse */
- X b2 = boolean;
- X if (result != last)
- X _ADDU(result,zero,last);
- X result = last;
- X boolean = (b1 & b2);
- X *remem |= code - remem - 1;
- X break;
- X case Andalso:
- X case Orelse:
- X gen(t->kids[0]);
- X b1 = boolean;
- X if (result != last)
- X _ADDU(result,zero,last);
- X saved = last;
- X remem = code;
- X if (t->t == Andalso)
- X *code++ = _BEQ(zero,last,0);
- X else
- X *code++ = _BNE(zero,last,0);
- X _NOP;
- X gen(t->kids[1]);
- X b2 = boolean;
- X if (result != saved)
- X _ADDU(result,zero,saved);
- X *remem |= code - remem - 1;
- X if (!(b1&b2))
- X _SLTU(zero,last,last); /* "normalize" expr to {0,1} */
- X result = saved;
- X boolean = 1;
- X break;
- X case Coordpair:
- X if (t->i > nfiles || t->i < 0)
- X error("no such buffer");
- X if (t->kids[0] != NULL) {
- X gen(t->kids[0]);
- X i = last;
- X } else
- X i = offset;
- X loadimm(tmp,(int)buf[t->i].data);
- X _ADDU(tmp,i,last);
- X _LBU(last,last,0);
- X _NOP;
- X result = last;
- X boolean = 0;
- X break;
- X default:
- X gen(t->kids[0]);
- X saved = result;
- X if (((Tree *)t->kids[1])->t == Num && (i = ((Tree *)t->kids[1])->i) < 32768 && i > -32768) {
- X binconst(t,result,i,last);
- X } else {
- X if (saved != rx && saved != ry && (last = findreg()) == -1) {
- X last = saved;
- X saved = -1;
- X _PUSH(last);
- X }
- X gen(t->kids[1]);
- X if (saved == -1) {
- X _POP(tmp);
- X _NOP;
- X binop(t,tmp,result,last);
- X } else {
- X binop(t,saved,result,last);
- X if (saved != rx && saved != ry)
- X freereg(saved);
- X }
- X }
- X result = last;
- X }
- X}
- X
- Xstatic void binop(Tree *t, int s1, int s2, int d) {
- X boolean = 0;
- X switch (t->t) {
- X default:
- X error("not a binop in binop!");
- X case Add:
- X _ADDU(s1,s2,d);
- X break;
- X case Sub:
- X _SUBU(s1,s2,d);
- X break;
- X case Mult:
- X _MULTU(s1,s2);
- X _MFLO(d);
- X break;
- X case Div:
- X _DIVU(s1,s2);
- X _MFLO(d);
- X break;
- X case Mod:
- X _DIVU(s1,s2);
- X _MFHI(d);
- X break;
- X case Gt:
- X _SLTU(s2,s1,d);
- X boolean = 1;
- X break;
- X case Lt:
- X _SLTU(s1,s2,d);
- X boolean = 1;
- X break;
- X case Ge:
- X _SLTU(s1,s2,d);
- X _XORI(d,1,d);
- X boolean = 1;
- X break;
- X case Le:
- X _SLTU(s2,s1,d);
- X _XORI(d,1,d);
- X boolean = 1;
- X break;
- X case Eq:
- X _XOR(s1,s2,d);
- X _SLTIU(d,1,d);
- X boolean = 1;
- X break;
- X case Ne:
- X _XOR(s1,s2,d);
- X _SLTIU(d,0,d);
- X boolean = 1;
- X break;
- X case Xor:
- X _XOR(s1,s2,d);
- X break;
- X case And:
- X _AND(s1,s2,d);
- X break;
- X case Or:
- X _OR(s1,s2,d);
- X break;
- X case Ll:
- X _SLLV(s1,s2,d);
- X break;
- X case Rr:
- X _SRLV(s1,s2,d);
- X break;
- X }
- X}
- X
- Xstatic void binconst(Tree *t, int s1, int s2, int d) {
- X int shift;
- X boolean = 0;
- X switch (t->t) {
- X default:
- X error("not a binop in binconst!");
- X case Add:
- X _ADDIU(s1,s2,d);
- X break;
- X case Sub:
- X _ADDIU(s1,-s2,d);
- X break;
- X case Mult:
- X case Div:
- X if (s2 < 0 || s2 & (s2 - 1) != 0) {
- X loadimm(tmp,s2);
- X if (t->t == Mult)
- X _MULTU(s1,tmp);
- X else
- X _DIVU(s1,tmp);
- X _MFLO(d);
- X } else {
- X for (shift = 0; s2 != 0; shift++, s2 >>= 1)
- X ;
- X if (shift == 0) {
- X if (t->t == Mult)
- X loadimm(d,0);
- X else
- X error("division by zero");
- X return;
- X } else if (t->t == Mult) {
- X _SLL(s1,--shift,d);
- X } else {
- X _SRL(s1,--shift,d);
- X }
- X }
- X break;
- X case Mod:
- X loadimm(tmp,s2);
- X _DIVU(s1,tmp);
- X _MFHI(d);
- X break;
- X case Gt:
- X if (s2 != 0) {
- X loadimm(tmp,s2);
- X _SLTU(tmp,s1,d);
- X } else
- X _SLTU(zero,s1,d);
- X boolean = 1;
- X break;
- X case Lt:
- X _SLTIU(s1,s2,d);
- X boolean = 1;
- X break;
- X case Ge:
- X _SLTIU(s1,s2,d);
- X _XORI(d,1,d);
- X boolean = 1;
- X break;
- X case Le:
- X if (s2 != 0) {
- X loadimm(tmp,s2);
- X _SLTU(tmp,s1,d);
- X } else
- X _SLTU(zero,s1,d);
- X _XORI(d,1,d);
- X boolean = 1;
- X break;
- X case Eq:
- X if (s2 != 0) {
- X _XORI(s1,s2,d);
- X _SLTIU(d,1,d);
- X } else
- X _SLTIU(s1,1,d);
- X boolean = 1;
- X break;
- X case Ne:
- X if (s2 != 0) {
- X _XORI(s1,s2,d);
- X _SLTIU(d,0,d);
- X } else
- X _SLTIU(s1,0,d);
- X boolean = 1;
- X break;
- X case Xor:
- X _XORI(s1,s2,d);
- X break;
- X case And:
- X _ANDI(s1,s2,d);
- X break;
- X case Or:
- X _ORI(s1,s2,d);
- X break;
- X case Ll:
- X _SLL(s1,s2,d);
- X break;
- X case Rr:
- X _SRL(s1,s2,d);
- X break;
- X }
- X}
- X
- Xstatic void dodump(Inst *prog, int size) {
- X if (debug) {
- X struct filehdr f;
- X struct scnhdr s;
- X int fd = creat(DUMPFILE, 0644);
- X if (fd < 0) {
- X perror(DUMPFILE);
- X exit(1);
- X }
- X f.f_magic = MIPSEBMAGIC;
- X f.f_nscns = 1;
- X f.f_timdat = 0;
- X f.f_symptr = 0;
- X f.f_nsyms = 0;
- X f.f_opthdr = 0;
- X f.f_flags = F_RELFLG | F_EXEC | F_LNNO | F_LSYMS | F_MINMAL;
- X strcpy(s.s_name, ".text");
- X s.s_paddr = 0;
- X s.s_vaddr = 0;
- X s.s_size = size;
- X s.s_scnptr = sizeof s + sizeof f;
- X s.s_relptr = 0;
- X s.s_lnnoptr = 0;
- X s.s_nreloc = 0;
- X s.s_nlnno = 0;
- X s.s_flags = 0;
- X write(fd, &f, sizeof f);
- X write(fd, &s, sizeof s);
- X write(fd, prog, size);
- X close(fd);
- X }
- X}
- X
- Xstatic void clearregs() {
- X int i;
- X for (i = 0; i < 8; i++)
- X regs[i] = 0;
- X}
- X
- Xstatic void freereg(int i) {
- X regs[i-8] = 0;
- X}
- X
- Xstatic int findreg() {
- X int i;
- X for (i = 0; i < 8; i++)
- X if (regs[i] == 0)
- X break;
- X if (i == 8)
- X return -1;
- X regs[i] = 1;
- X return i+8;
- X}
- END_OF_FILE
- if test 9124 -ne `wc -c <'mipsgen.c'`; then
- echo shar: \"'mipsgen.c'\" unpacked with wrong size!
- fi
- # end of 'mipsgen.c'
- fi
- if test -f 'mk.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mk.c'\"
- else
- echo shar: Extracting \"'mk.c'\" \(779 characters\)
- sed "s/^X//" >'mk.c' <<'END_OF_FILE'
- X#include "pico.h"
- X
- Xextern Tree *mk(enum tree t,Tree *a,Tree *b) {
- X Tree *new = treealloc(2);
- X new->kids[0] = a;
- X new->kids[1] = b;
- X new->t = t;
- X return new;
- X}
- X
- Xextern Tree *mkNum(int i) {
- X Tree *new = treealloc(0);
- X new->i = i;
- X new->t = Num;
- X return new;
- X}
- X
- Xextern Tree *mkCoord(int file,Tree *coord) {
- X Tree *new = treealloc(1);
- X new->i = file;
- X new->kids[0] = coord;
- X new->t = Coordpair;
- X return new;
- X}
- X
- Xextern Tree *mkun(enum tree t,void *a) {
- X Tree *new = treealloc(1);
- X new->kids[0] = a;
- X new->t = t;
- X return new;
- X}
- X
- Xextern Tree *mkCond(Tree *a, Tree *b, Tree *c) {
- X Tree *new = treealloc(3);
- X new->kids[0] = a;
- X new->kids[1] = b;
- X new->kids[2] = c;
- X new->t = Cond;
- X return new;
- X}
- X
- Xextern Tree *mkempty(enum tree t) {
- X Tree *new = treealloc(0);
- X new->t = t;
- X return new;
- X}
- END_OF_FILE
- if test 779 -ne `wc -c <'mk.c'`; then
- echo shar: \"'mk.c'\" unpacked with wrong size!
- fi
- # end of 'mk.c'
- fi
- if test -f 'nodpy.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'nodpy.c'\"
- else
- echo shar: Extracting \"'nodpy.c'\" \(25 characters\)
- sed "s/^X//" >'nodpy.c' <<'END_OF_FILE'
- Xextern void display(){
- X}
- END_OF_FILE
- if test 25 -ne `wc -c <'nodpy.c'`; then
- echo shar: \"'nodpy.c'\" unpacked with wrong size!
- fi
- # end of 'nodpy.c'
- fi
- if test -f 'patchlevel.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'patchlevel.h'\"
- else
- echo shar: Extracting \"'patchlevel.h'\" \(79 characters\)
- sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
- X/*
- X** Current release information.
- X*/
- X#define RELEASE 1
- X#define PATCHLEVEL 0
- END_OF_FILE
- if test 79 -ne `wc -c <'patchlevel.h'`; then
- echo shar: \"'patchlevel.h'\" unpacked with wrong size!
- fi
- # end of 'patchlevel.h'
- fi
- if test -f 'pico.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pico.h'\"
- else
- echo shar: Extracting \"'pico.h'\" \(1431 characters\)
- sed "s/^X//" >'pico.h' <<'END_OF_FILE'
- X#include <stdio.h>
- X#include <stdlib.h>
- X
- Xenum tree {
- X Num, Id, Bang, Not, Neg, Add, Sub, Mult, Div,
- X Mod, Or, Xor, And, Eq, Ne, Andalso, Orelse, Cond,
- X Gt, Lt, Ge, Le, Ll, Rr, Xcoord, Ycoord, Coordpair,
- X Write, Read, Files, Undo, Quit
- X};
- X
- Xtypedef struct Tree Tree;
- Xtypedef struct Buf Buf;
- X
- Xstruct Tree {
- X enum tree t;
- X int i;
- X void *kids[3];
- X};
- X
- Xstruct Buf {
- X char *name;
- X unsigned char *data;
- X};
- X
- X#define DEF_X 512
- X#define DEF_Y 512
- X#define NFILES 128
- X#define DUMPFILE "pico.out"
- X
- X/* main.c */
- Xextern int main(int, char *[]);
- Xextern void syntax_error(int);
- Xextern void error(char *);
- Xextern unsigned char data[];
- Xextern int debug, saw_eof;
- Xextern Tree *tree;
- X
- X/* expr.c */
- Xextern Tree *expr(void);
- X
- X/* mk.c */
- Xextern Tree *mk(enum tree,Tree *,Tree *);
- Xextern Tree *mkCond(Tree *,Tree *,Tree *);
- Xextern Tree *mkCoord(int,Tree *);
- Xextern Tree *mkun(enum tree,void *);
- Xextern Tree *mkNum(int);
- Xextern Tree *mkempty(enum tree);
- X
- X/* gen.c */
- Xextern int calc(Tree *);
- Xextern void compile(Tree *);
- X
- X/* dpy.c */
- Xextern void display(unsigned char *);
- X
- X/* alloc.c */
- Xextern void *ealloc(size_t);
- Xextern void *alloc(size_t);
- Xextern void afree(void);
- X#ifndef offsetof
- X#define offsetof(t, m) ((size_t) &((t *)0)->m)
- X#endif
- X#define treealloc(x) alloc(offsetof(Tree,kids[x]));
- X
- X/* file.c */
- Xextern int findfile(char *);
- Xextern void showfiles(void);
- Xextern int readfile(char *);
- Xextern void writefile(char *);
- Xextern Buf buf[];
- Xextern int nfiles;
- END_OF_FILE
- if test 1431 -ne `wc -c <'pico.h'`; then
- echo shar: \"'pico.h'\" unpacked with wrong size!
- fi
- # end of 'pico.h'
- fi
- if test -f 'sparcgen.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sparcgen.c'\"
- else
- echo shar: Extracting \"'sparcgen.c'\" \(10714 characters\)
- sed "s/^X//" >'sparcgen.c' <<'END_OF_FILE'
- X#include <sys/exec.h>
- X#include <unistd.h>
- X#include <string.h>
- X#include "pico.h"
- X
- Xtypedef unsigned long Inst;
- X
- Xstatic void gen(Tree *t);
- Xstatic void binop(Tree *t, int s1, int s2, int d);
- Xstatic void binconst(Tree *t, int s1, int s2, int d);
- Xstatic void dodump(Inst *, int);
- Xstatic void clearregs(void);
- Xstatic void freereg(int);
- Xstatic int findreg(void);
- Xstatic int mul(int,int), div(int,int), mod(int,int);
- X
- Xstatic Inst *code;
- Xstatic ccset, boolean, last = 18, regs[6], spp, sppmax, result;
- X
- X#define zero 0
- X#define tmp 1
- X#define base 24 /* first arg */
- X#define offset 25 /* etc. */
- X#define a_mul 26
- X#define a_div 27
- X#define a_mod 28
- X#define rx 16
- X#define ry 17
- X#define sp 14
- X#define o0 8 /* first arg out */
- X#define o1 9
- X
- X#define OP(rd,op,rs,i,r_or_d) ((2<<30)|(rd<<25)|(op<<19)|(rs<<14)|(i<<13)|(r_or_d&017777))
- X#define MOP(rd,op,rs,i,r_or_d) ((3<<30)|(rd<<25)|(op<<19)|(rs<<14)|(i<<13)|(r_or_d&017777))
- X#define SETHI(rd,op,imm) ((rd<<25)|(op<<22)|(imm&017777777))
- X
- X#define _ADD(a,b,c) *code++ = OP(c,000,a,0,b)
- X#define _ADDcc(a,b,c) *code++ = OP(c,020,a,0,b)
- X#define _SUB(a,b,c) *code++ = OP(c,004,a,0,b)
- X#define _SUBcc(a,b,c) *code++ = OP(c,024,a,0,b)
- X#define _XOR(a,b,c) *code++ = OP(c,003,a,0,b)
- X#define _XORcc(a,b,c) *code++ = OP(c,023,a,0,b)
- X#define _OR(a,b,c) *code++ = OP(c,002,a,0,b)
- X#define _ORcc(a,b,c) *code++ = OP(c,022,a,0,b)
- X#define _AND(a,b,c) *code++ = OP(c,001,a,0,b)
- X#define _ANDcc(a,b,c) *code++ = OP(c,021,a,0,b)
- X#define _NOR(a,b,c) *code++ = OP(c,006,a,0,b)
- X#define _XORI(a,b,c) *code++ = OP(c,003,a,1,b)
- X#define _XORIcc(a,b,c) *code++ = OP(c,023,a,1,b)
- X#define _ORI(a,b,c) *code++ = OP(c,002,a,1,b)
- X#define _ORIcc(a,b,c) *code++ = OP(c,022,a,1,b)
- X#define _ADDI(a,b,c) *code++ = OP(c,000,a,1,b)
- X#define _ADDIcc(a,b,c) *code++ = OP(c,020,a,1,b)
- X#define _ANDI(a,b,c) *code++ = OP(c,001,a,1,b)
- X#define _ANDIcc(a,b,c) *code++ = OP(c,021,a,1,b)
- X#define _LBU(a,b,c) *code++ = MOP(a,001,b,0,c)
- X#define _LBIU(a,b,c) *code++ = MOP(a,001,b,1,c)
- X#define _SB(a,b,c) *code++ = MOP(a,005,b,0,c)
- X#define _SBI(a,b,c) *code++ = MOP(a,005,b,1,c)
- X#define _LW(a,b,c) *code++ = MOP(a,000,b,0,c)
- X#define _LWI(a,b,c) *code++ = MOP(a,000,b,1,c)
- X#define _SW(a,b,c) *code++ = MOP(a,004,b,0,c)
- X#define _SWI(a,b,c) *code++ = MOP(a,004,b,1,c)
- X#define _SETHI(a,b) *code++ = SETHI(a,04,b>>10)
- X#define _SLL(a,b,c) *code++ = OP(c,045,a,0,b)
- X#define _SRL(a,b,c) *code++ = OP(c,046,a,0,b)
- X#define _SLLI(a,b,c) *code++ = OP(c,045,a,1,b)
- X#define _SRLI(a,b,c) *code++ = OP(c,046,a,1,b)
- X#define _CMP(a,b) *code++ = OP(zero,024,a,0,b) /* _SUBcc(a,b,zero); */
- X#define _CMPI(a,b) *code++ = OP(zero,024,a,1,b) /* _SUBIcc(a,b,zero); */
- X#define _B(cond,disp) SETHI(cond,02,disp)
- X#define ALWAYS 010
- X#define EQ 001
- X#define NE 011
- X#define GE 013
- X#define LE 002
- X#define GT 012
- X#define LT 003
- X#define _JAL(a) *code++ = OP(15,070,a,0,zero)
- X#define _SAVE(a) *code++ = OP(sp,074,sp,1,a)
- X#define _RET *code++ = 0x81c7e008 /* jmpl %o7+8,%g0 */
- X#define _RESTORE *code++ = 0x81e80000 /* restore %g0,%g0,%g0 */
- X#define _NOP *code++ = SETHI(zero,04,0)
- X
- X#define _PUSH(a) {\
- X _SW(a,sp,spp);\
- X spp += 4;\
- X if (spp > sppmax)\
- X sppmax = spp;\
- X}
- X
- X#define _POP(a) {\
- X spp -= 4;\
- X _LW(a,sp,spp);\
- X}
- X
- Xstatic void loadimm(int i, int j) {
- X if (j > 0x1777 || j < 0) {
- X _SETHI(i,j);
- X _ORIcc(i,(j&01777),i);
- X } else
- X _ORIcc(zero,j,i);
- X}
- X
- Xextern void compile(Tree *t) {
- X Inst prog[1024], *remem1, *remem2;
- X void (*progp)() = (void (*)()) prog;
- X code = prog;
- X clearregs();
- X last = findreg();
- X code = prog;
- X _SAVE(0); /* value is or'ed in later */
- X loadimm(ry,DEF_Y-1);
- X remem1 = code;
- X loadimm(rx,DEF_X-1);
- X remem2 = code;
- X gen(t);
- X _SB(result,base,offset);
- X _ADDI(offset,-1,offset);
- X _CMP(rx,zero);
- X *code = _B(NE,remem2-code); code++;
- X _ADDI(rx,-1,rx);
- X _CMP(ry,zero);
- X *code = _B(NE,remem1-code); code++;
- X _ADDI(ry,-1,ry);
- X _RET;
- X _RESTORE;
- X *prog |= (-(sppmax+80))&017777;
- X dodump(prog, (code - prog) * sizeof (Inst));
- X progp(buf[0].data, (DEF_X*DEF_Y) - 1, mul, div, mod);
- X}
- X
- Xstatic int mul(int a, int b) {
- X return a*b;
- X}
- X
- Xstatic int div(int a, int b) {
- X return a/b;
- X}
- X
- Xstatic int mod(int a, int b) {
- X return a%b;
- X}
- X
- Xstatic void gen(Tree *t) {
- X Inst *remem;
- X int i, saved, b1, b2, c1, c2;
- X switch (t->t) {
- X case Num:
- X if (t->i == 0) {
- X result = zero;
- X ccset = 0;
- X boolean = 1;
- X } else {
- X loadimm(result = last, t->i);
- X boolean = !(t->i & ~1);
- X ccset = 1;
- X }
- X break;
- X case Xcoord:
- X result = rx;
- X boolean = 0;
- X ccset = 0;
- X break;
- X case Ycoord:
- X result = ry;
- X boolean = 0;
- X ccset = 0;
- X break;
- X case Bang:
- X gen(t->kids[0]);
- X if (!ccset)
- X _CMP(result,zero);
- X *code++ = _B(EQ,3);
- X _ADDIcc(zero,1,last);
- X _ADDIcc(zero,0,last);
- X result = last;
- X boolean = 1;
- X ccset = 1;
- X break;
- X case Not:
- X gen(t->kids[0]);
- X _XORIcc(result,-1,last);
- X result = last;
- X boolean = 0;
- X ccset = 1;
- X break;
- X case Neg:
- X gen(t->kids[0]);
- X _SUBcc(zero,result,last);
- X result = last;
- X boolean = 0;
- X ccset = 1;
- X break;
- X case Cond:
- X gen(t->kids[0]); /* test */
- X if (!ccset)
- X _CMP(result,zero);
- X remem = code;
- X *code++ = _B(EQ,0);
- X _NOP;
- X gen(t->kids[1]); /* iftrue */
- X b1 = boolean;
- X c1 = ccset;
- X if (result != last)
- X _ADD(result,zero,last);
- X *remem |= code - remem + 1;
- X remem = code - 1;
- X *code = code[-1];
- X code[-1] = _B(ALWAYS,0); /* fill delay slot */
- X code++;
- X gen(t->kids[2]); /* iffalse */
- X b2 = boolean;
- X c2 = ccset;
- X if (result != last)
- X _ADD(result,zero,last);
- X result = last;
- X boolean = (b1 & b2);
- X ccset = (c1 & c2);
- X *remem |= code - remem;
- X break;
- X case Andalso:
- X case Orelse:
- X gen(t->kids[0]);
- X b1 = boolean;
- X if (result != last)
- X _ADDcc(result,zero,last);
- X else if (!ccset)
- X _CMP(result,zero);
- X saved = last;
- X remem = code;
- X if (t->t == Andalso)
- X *code++ = _B(EQ,0);
- X else
- X *code++ = _B(NE,0);
- X _NOP;
- X gen(t->kids[1]);
- X b2 = boolean;
- X if (result != saved) {
- X _ADDcc(result,zero,saved);
- X ccset = 1;
- X }
- X result = saved;
- X *remem |= code - remem;
- X if (!(b1&b2)) { /* "normalize" expr to {0,1} */
- X if (!ccset)
- X _CMP(result,0);
- X *code++ = _B(NE,3);
- X _ADDIcc(zero,0,result);
- X _ADDIcc(zero,1,result);
- X ccset = 1;
- X }
- X boolean = 1;
- X break;
- X case Coordpair:
- X if (t->i > nfiles || t->i < 0)
- X error("no such buffer");
- X if (t->kids[0] != NULL) {
- X gen(t->kids[0]);
- X i = last;
- X } else
- X i = offset;
- X loadimm(tmp,(int)buf[t->i].data);
- X _LBU(last,tmp,i);
- X result = last;
- X ccset = 0;
- X boolean = 0;
- X break;
- X default:
- X gen(t->kids[0]);
- X saved = result;
- X if (((Tree *)t->kids[1])->t == Num && (i = ((Tree *)t->kids[1])->i) < 4096 && i > -4096) {
- X binconst(t,result,i,last);
- X } else {
- X if (saved != rx && saved != ry && (last = findreg()) == -1) {
- X last = saved;
- X saved = -1;
- X _PUSH(last);
- X }
- X gen(t->kids[1]);
- X if (saved == -1) {
- X _POP(tmp);
- X binop(t,tmp,result,last);
- X } else {
- X binop(t,saved,result,last);
- X if (saved != rx && saved != ry)
- X freereg(saved);
- X }
- X }
- X result = last;
- X }
- X}
- X
- Xstatic void binop(Tree *t, int s1, int s2, int d) {
- X boolean = 0;
- X ccset = 1;
- X switch (t->t) {
- X default:
- X error("not a binop in binop!");
- X case Add:
- X _ADDcc(s1,s2,d);
- X break;
- X case Sub:
- X _SUBcc(s1,s2,d);
- X break;
- X case Mult:
- X _ADD(zero,s1,o0);
- X _JAL(a_mul);
- X _ADD(zero,s2,o1);
- X _ADDcc(zero,o0,d);
- X break;
- X case Div:
- X _ADD(zero,s1,o0);
- X _JAL(a_div);
- X _ADD(zero,s2,o1);
- X _ADDcc(zero,o0,d);
- X break;
- X case Mod:
- X _ADD(zero,s1,o0);
- X _JAL(a_mod);
- X _ADD(zero,s2,o1);
- X _ADDcc(zero,o0,d);
- X break;
- X case Gt:
- X _CMP(s1,s2);
- X *code++ = _B(GT,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Lt:
- X _CMP(s1,s2);
- X *code++ = _B(LT,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Ge:
- X _CMP(s1,s2);
- X *code++ = _B(GE,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Le:
- X _CMP(s1,s2);
- X *code++ = _B(LE,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Eq:
- X _CMP(s1,s2);
- X *code++ = _B(EQ,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Ne:
- X _CMP(s1,s2);
- X *code++ = _B(NE,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Xor:
- X _XORcc(s1,s2,d);
- X break;
- X case And:
- X _ANDcc(s1,s2,d);
- X break;
- X case Or:
- X _ORcc(s1,s2,d);
- X break;
- X case Ll:
- X _SLL(s1,s2,d);
- X ccset = 0;
- X break;
- X case Rr:
- X _SRL(s1,s2,d);
- X ccset = 0;
- X break;
- X }
- X}
- X
- Xstatic void binconst(Tree *t, int s1, int s2, int d) {
- X int shift;
- X boolean = 0;
- X ccset = 1;
- X switch (t->t) {
- X default:
- X error("not a binop in binconst!");
- X case Add:
- X _ADDIcc(s1,s2,d);
- X break;
- X case Sub:
- X _ADDIcc(s1,-s2,d);
- X break;
- X case Mult:
- X case Div:
- X if (s2 < 0 || s2 & (s2 - 1) != 0) {
- X loadimm(s2,o1);
- X _JAL(((t->t == Mult) ? a_mul : a_div));
- X _ADD(zero,s1,o0);
- X _ADDcc(zero,o0,d);
- X } else {
- X for (shift = 0; s2 != 0; shift++, s2 >>= 1)
- X ;
- X if (shift == 0) {
- X if (t->t == Mult)
- X loadimm(d,0);
- X else
- X error("division by zero");
- X return;
- X } else if (t->t == Mult) {
- X _SLLI(s1,--shift,d);
- X } else {
- X _SRLI(s1,--shift,d);
- X }
- X ccset = 0;
- X }
- X break;
- X case Mod:
- X loadimm(s2,o1);
- X _JAL(a_mod);
- X _ADD(zero,s1,o0);
- X _ADDcc(zero,o0,d);
- X break;
- X case Gt:
- X _CMPI(s1,s2);
- X *code++ = _B(GT,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Lt:
- X _CMPI(s1,s2);
- X *code++ = _B(LT,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Ge:
- X _CMPI(s1,s2);
- X *code++ = _B(GE,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Le:
- X _CMPI(s1,s2);
- X *code++ = _B(LE,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Eq:
- X _CMPI(s1,s2);
- X *code++ = _B(EQ,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Ne:
- X _CMPI(s1,s2);
- X *code++ = _B(NE,3);
- X _ADDIcc(zero,0,d);
- X _ADDIcc(zero,1,d);
- X boolean = 1;
- X break;
- X case Xor:
- X _XORIcc(s1,s2,d);
- X break;
- X case And:
- X _ANDIcc(s1,s2,d);
- X break;
- X case Or:
- X _ORIcc(s1,s2,d);
- X break;
- X case Ll:
- X _SLLI(s1,s2,d);
- X ccset = 0;
- X break;
- X case Rr:
- X _SRLI(s1,s2,d);
- X ccset = 0;
- X break;
- X }
- X}
- X
- Xstatic void dodump(Inst *prog, int size) {
- X if (debug) {
- X int fd = creat("pico.out", 0644);
- X struct exec exec;
- X exec.a_machtype = M_SPARC;
- X exec.a_magic = OMAGIC;
- X exec.a_text = size;
- X exec.a_data = 0;
- X exec.a_bss = 0;
- X exec.a_syms = 0;
- X exec.a_entry = 0;
- X exec.a_trsize = 0;
- X exec.a_drsize = 0;
- X if (fd < 0) {
- X perror("pico.out");
- X exit(1);
- X }
- X write(fd, &exec, sizeof exec);
- X write(fd, prog, size);
- X close(fd);
- X }
- X}
- X
- Xstatic void clearregs() {
- X int i;
- X for (i = 0; i < 6; i++)
- X regs[i] = 0;
- X}
- X
- Xstatic void freereg(int i) {
- X regs[i-18] = 0;
- X}
- X
- Xstatic int findreg() {
- X int i;
- X for (i = 0; i < 6; i++)
- X if (regs[i] == 0)
- X break;
- X if (i == 6)
- X return -1;
- X regs[i] = 1;
- X return i+18;
- X}
- END_OF_FILE
- if test 10714 -ne `wc -c <'sparcgen.c'`; then
- echo shar: \"'sparcgen.c'\" unpacked with wrong size!
- fi
- # end of 'sparcgen.c'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-